﻿using System;
using System.Collections.Generic;
using System.Drawing;
using Controls;
using DotNet.Highcharts;
using DotNet.Highcharts.Enums;
using DotNet.Highcharts.Helpers;
using DotNet.Highcharts.Options;
using Model;
using Point = DotNet.Highcharts.Options.Point;
using Title = DotNet.Highcharts.Options.Title;

namespace FrontEnd.forms
{
    public partial class General : Page
    {
        private Functions _functions;

        protected void Page_Load(object sender, EventArgs e)
        {
            _functions = new Functions(Conf.Db("CrazyWowStatsEntities"));

            GenerateGeneralStatistics();
            GenerateClassDistribution();
            GenerateGenderDistribution();
            GenerateRaceDistribution();
        }

        private void GenerateClassDistribution()
        {
            Point[] data = ParseClassDistribution(_functions.GetClassDistribution());
            classDistributionChart.Text = CreateChart("Class", "", data);
        }

        private void GenerateGenderDistribution()
        {
            Point[] data = ParseGenderDistribution(_functions.GetGenderDistribution());
            genderDistributionChart.Text = CreateChart("Gender", "", data);
        }

        private void GenerateRaceDistribution()
        {
            Point[] data = ParseRaceDistribution(_functions.GetRaceDistribution());
            raceDistributionChart.Text = CreateChart("Race", "", data);
        }

        private void GenerateGeneralStatistics()
        {
            Dictionary<string, long> generalStatistics = _functions.GetGeneralStatistics();

            totalCharacters.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.TotalCharacters]);
            averageCharacterLevel.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.AverageLevel]);
            charactersAtMaxLevel.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.CharactersAtMaxLevel]);
            maxAchievementPoints.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.MaxAchievementPoints]);
            averageAchievementPoints.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.AverageAchievementPoints]);
            totalHonorableKills.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.TotalHonorableKills]);
            maxHonorableKills.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.MaxHonorableKills]);
            averageHonorableKills.Text = String.Format("{0:#,###}", generalStatistics[Constants.GeneralStatistics.AverageHonorableKills]);
        }

        private static Point[] ParseClassDistribution(Dictionary<Enums.Class, int> result)
        {
            Point deathKnightResult = CreatePoint(result[Enums.Class.DeathKnight], Constants.Class.DeathKnight, false, Enums.ClassColors.DeathKnight);
            Point druidResult = CreatePoint(result[Enums.Class.Druid], Constants.Class.Druid, false, Enums.ClassColors.Druid);
            Point hunterResult = CreatePoint(result[Enums.Class.Hunter], Constants.Class.Hunter, false, Enums.ClassColors.Hunter);
            Point mageResult = CreatePoint(result[Enums.Class.Mage], Constants.Class.Mage, false, Enums.ClassColors.Mage);
            Point paladinResult = CreatePoint(result[Enums.Class.Paladin], Constants.Class.Paladin, false, Enums.ClassColors.Paladin);
            Point priestResult = CreatePoint(result[Enums.Class.Priest], Constants.Class.Priest, false, Enums.ClassColors.Priest);
            Point rogueResult = CreatePoint(result[Enums.Class.Rogue], Constants.Class.Rogue, false, Enums.ClassColors.Rogue);
            Point shamanResult = CreatePoint(result[Enums.Class.Shaman], Constants.Class.Shaman, false, Enums.ClassColors.Shaman);
            Point warlockResult = CreatePoint(result[Enums.Class.Warlock], Constants.Class.Warlock, false, Enums.ClassColors.Warlock);
            Point warriorResult = CreatePoint(result[Enums.Class.Warrior], Constants.Class.Warrior, false, Enums.ClassColors.Warrior);
            var parsedResult = new[] {deathKnightResult, druidResult, hunterResult, mageResult, paladinResult, priestResult, rogueResult, shamanResult, warlockResult, warriorResult};

            return parsedResult;
        }

        private static Point[] ParseGenderDistribution(Dictionary<string, int> result)
        {
            Point femaleResult = CreatePoint(result[Constants.Gender.Male], Constants.Gender.Male, false, Enums.GenderColors.Male);
            Point maleResult = CreatePoint(result[Constants.Gender.Female], Constants.Gender.Female, false, Enums.GenderColors.Female);

            var parsedResult = new[] {femaleResult, maleResult};
            return parsedResult;
        }

        private static Point[] ParseRaceDistribution(Dictionary<Enums.Race, int> result)
        {
            Point bloodElfResult = CreatePoint(result[Enums.Race.BloodElf], Constants.Race.BloodElf, false, Enums.RaceColors.BloodElf);
            Point draeneiResult = CreatePoint(result[Enums.Race.Draenei], Constants.Race.Drainei, false, Enums.RaceColors.Draenei);
            Point dwarfResult = CreatePoint(result[Enums.Race.Dwarf], Constants.Race.Dwarf, false, Enums.RaceColors.Dwarf);
            Point gnomeResult = CreatePoint(result[Enums.Race.Gnome], Constants.Race.Gnome, false, Enums.RaceColors.Gnome);
            Point goblinResult = CreatePoint(result[Enums.Race.Goblin], Constants.Race.Goblin, false, Enums.RaceColors.Goblin);
            Point humanResult = CreatePoint(result[Enums.Race.Human], Constants.Race.Human, false, Enums.RaceColors.Human);
            Point nightElfResult = CreatePoint(result[Enums.Race.NightElf], Constants.Race.NightElf, false, Enums.RaceColors.NightElf);
            Point orcResult = CreatePoint(result[Enums.Race.Orc], Constants.Race.Orc, false, Enums.RaceColors.Orc);
            Point taurenResult = CreatePoint(result[Enums.Race.Tauren], Constants.Race.Tauren, false, Enums.RaceColors.Tauren);
            Point trollResult = CreatePoint(result[Enums.Race.Troll], Constants.Race.Troll, false, Enums.RaceColors.Troll);
            Point undeadResult = CreatePoint(result[Enums.Race.Undead], Constants.Race.Undead, false, Enums.RaceColors.Undead);
            Point worgenResult = CreatePoint(result[Enums.Race.Worgen], Constants.Race.Worgen, false, Enums.RaceColors.Worgen);
            var parsedResult = new[] {bloodElfResult, draeneiResult, dwarfResult, gnomeResult, goblinResult, humanResult, nightElfResult, orcResult, taurenResult, trollResult, undeadResult, worgenResult};

            return parsedResult;
        }

        private static string CreateChart(string chartName, string chartTitle, Point[] data)
        {
            Highcharts chart = new Highcharts(chartName).
                InitChart(
                    new Chart
                        {
                            PlotShadow = false
                        }
                ).
                SetCredits(new Credits
                               {
                                   Enabled = false
                               }).
                SetTitle(new Title
                             {
                                 Text = chartTitle,
                                 Style = "color:'#000000', fontSize: '18px', fontFamily: 'Verdana'"
                             }).
                SetTooltip(new Tooltip
                               {
                                   Formatter = "function() { return '<b>'+ this.point.name +'</b>: '+ RoundNumber(this.percentage, 2) +' %'; }"
                               }).
                SetPlotOptions(new PlotOptions
                                   {
                                       Series = new PlotOptionsSeries
                                                    {
                                                        AllowPointSelect = false,
                                                        Cursor = Cursors.Pointer,
                                                        DataLabels = new PlotOptionsPieDataLabels
                                                                         {
                                                                             Color = ColorTranslator.FromHtml("#000000"),
                                                                             ConnectorColor = ColorTranslator.FromHtml("#000000"),
                                                                             Formatter = "function() { return '<b>'+ this.point.name +'</b>: '+ this.y; }"
                                                                         }
                                                    }
                                   }).
                SetSeries(new Series
                              {
                                  Type = ChartTypes.Pie,
                                  Data = new Data(data)
                              });

            return chart.ToHtmlString();
        }

        private static Point CreatePoint(int? y, string name, bool sliced, Color color)
        {
            var point = new Point
                            {
                                Y = y,
                                Name = name,
                                Sliced = sliced,
                                Color = color
                            };
            return point;
        }
    }
}